FlawOpen

flawopen.com/Справочник/Next.js Server Actions CSRF

CSRF в Next.js Server Actions: проверка Origin и безопасная настройка

CWE-352: Cross-Site Request Forgery (CSRF)Руководство по безопасности фреймворка
Краткий ответ

Server Actions в Next.js используют POST и сравнивают host из Origin с x-forwarded-host или host. Это похоже на проверку, что приглашение посетителя указывает на то же место, которое ожидает сервер. Проверка помогает блокировать межсайтовые отправки, но не выдает разрешение: каждое действие должно аутентифицировать пользователя, проверять ввод и права.

Есть важное ограничение: текущая документация Next.js говорит, что запрос без Origin пропускается с предупреждением. Обратные прокси также влияют на сравниваемый host. Считайте проверку одним уровнем защиты и настройте прокси на передачу доверенного host.

Origin
Источник запроса, переданный браузером; Next.js сравнивает его host с host приложения.
Host / X-Forwarded-Host
Значение host для сравнения. Прокси должен задавать или проверять передаваемые заголовки.
allowedOrigins
Явный список дополнительных Origin-host, разрешенных для Server Actions. Next.js поддерживает точные имена и шаблоны wildcard.
Authorization
Проверка для конкретного действия: может ли аутентифицированный пользователь выполнить эту операцию над этим объектом?

Как работает встроенная CSRF-проверка Server Actions

1

Браузер отправляет Server Action

Server Action вызывается HTTP-методом POST. SameSite по умолчанию блокирует многие межсайтовые отправки, но одного POST недостаточно для полноценной CSRF-защиты.

2

Next.js сравнивает host

Если Origin присутствует, Next.js сравнивает его host с x-forwarded-host или host. Несовпадение отклоняется, кроме случая, когда Origin-host входит в serverActions.allowedOrigins.

3

Действие всё равно применяет собственные правила

После проверки запроса действие должно аутентифицировать пользователя, проверить каждый аргумент и разрешить операцию. Идентификаторы действий и скрытые поля формы не контролируют доступ.

Важные ограничения: отсутствующий Origin и allowedOrigins

Отсутствие Origin по документированному поведению не отклоняется

Согласно текущей документации, запросы без Origin продолжаются с предупреждением. Не считайте, что каждый запрос прошёл сравнение. Выясните причину и всё равно выполняйте аутентификацию, авторизацию и проверку данных внутри действия.

Wildcard расширяет набор доверенных Origin

allowedOrigins принимает точные host и шаблоны: * соответствует одной метке, ** — одной или нескольким. Разрешайте только необходимые домены и поддомены, контролируемые организацией. Шаблон для поддоменов, которыми управляют пользователи, может доверить чужой источник.

Настройте обратный прокси как часть границы безопасности

Next.js использует x-forwarded-host или host при сравнении. Пограничный прокси должен удалять переданные клиентом forwarding-заголовки и задавать значение по проверенному публичному имени; приложение должно быть доступно только через доверенный прокси. Если прокси передает внутреннее имя, укажите в allowedOrigins только нужный публичный Origin. Не устраняйте несовпадение доверием к произвольным host.

СЛИШКОМ ШИРОКОЕ ДОВЕРИЕ
// 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 приводило к документированным SSRF-уязвимостям в Server Actions. CVE-2024-34351 затрагивала самостоятельно размещенные версии до 14.1.1, когда действие выполняло относительный редирект с началом /, а Host можно было изменить. Отдельная рекомендация Vercel за июль 2026 года описывает SSRF и возможное раскрытие внутренних значений, если пользовательские серверы позволяют клиенту контролировать связанные с host заголовки; исправления указаны в 15.5.21 и 16.2.11. Это ошибки доверия к host, а не свидетельство обхода CSRF-проверки Origin.

Для проблемы из рекомендации 2026 года обновитесь до исправленной версии. Пока обновление невозможно, фиксируйте или проверяйте Host и X-Forwarded-Host на прокси или внешнем узле. В рекомендации также указан __NEXT_PRIVATE_ORIGIN как дополнительный обходной путь начиная с 14.2.0. Перед применением сверьте затронутые и поддерживаемые ветки с рекомендацией.

Авторизуйте и проверяйте каждую 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");
}

Контрольный список CSRF и авторизации Server Actions

Источники

См. также Межсайтовая подделка запросов (CSRF, CWE-352): как работает и как предотвратить — flawopen.com Заменяет ли SameSite=Strict CSRF-токены? CSRF-токен для GET: когда он нужен? JWT в localStorage или cookie HttpOnly: что безопаснее? — flawopen.com