По фреймворкам
Безопасность Next.js — Server Actions, переменные окружения и CVE зависимостей
Инциденты Next.js происходят на границе сервер/клиент: утечка переменных окружения, отсутствие авторизации в Server Actions и известные CVE зависимостей. Держите секреты на сервере, ограничивайте по владельцу, мониторьте CVE. Защитно, без шагов атаки.
Для тех, кто эксплуатирует приложение на Next.js. Здесь нет шагов атаки — только инциденты, происходящие на границе сервер/клиент, и как их закрыть. Полную картину смотрите в хабе по безопасности для каждого фреймворка.
Большая тройка ловушек (на границе)
Экранирование и маршрутизация Next.js превосходны, но эти три — ваши, их закрывать, следя за границей.
① Утечка переменных окружения
Неверно использован NEXT_PUBLIC_ или секреты переданы клиенту. Запечены в бандл, видны посетителям.
② Пробелы в авторизации действий
Нет проверки владельца в Server Actions / Route Handlers. Подмените ID — оперируете чужими данными.
③ Известные CVE зависимостей
CVE ядра/зависимостей (вкл. RCE) остались незакрытыми. Судите по работающей версии, быстро патчите.
Как их закрыть (3 шага)
Держите секреты только на сервере
NEXT_PUBLIC_ только к безопасным для браузера значениям; никогда — к ключам API или данным подключения. Читайте секреты только внутри серверных компонентов / Server Actions / Route Handlers и держите их вне props и ответов. (→ файлы .env и секреты)Авторизуйте в каждом Server Action / Route Handler
Машинно мониторьте CVE зависимостей и быстро патчите
Частое (опасно)
- секреты с префиксом
NEXT_PUBLIC_, открытые клиенту - Server Actions трактуются как «залогинен = разрешено»
- запросы внешних URL на сервере без защиты (SSRF)
- известные CVE зависимостей остаются незакрытыми
Правильно
- секреты только на сервере, никогда не отправляются клиенту
- действия выполняют авторизацию с проверкой владельца
- запросы URL идут через защиту от SSRF (блок внутренних IP, белый список)
- CVE зависимостей машинно мониторятся + быстро патчатся
Взгляд этого сайта: управляйте «границей и зависимостями», а не ядром
Наш сайт работает на Next.js, и центр тяжести, который мы реально охраняем, — не эффектные настройки, а граница сервер/клиент и свежесть зависимостей. Секреты остаются на сервере, публичные точки входа (Server Actions / Route Handlers) всегда несут авторизацию, а зависимости проходят аудит CVE перед каждым деплоем. Наше собственное происхождение — это инцидент «незакрытая CVE, автоматически эксплуатированная», поэтому машинный мониторинг зависимостей — привычка высшего приоритета. Любой код, запрашивающий внешний URL, идёт через наш собственный шлюз, безопасный к SSRF, чтобы не достать до внутренних IP или метаданных (→ что такое SSRF).
Читать дальше
- Хаб: безопасность по фреймворкам · безопасность Laravel
- Зависимости: не отставать от CVE · плейбук реагирования на уязвимости
- Глоссарий: что такое IDOR · что такое SSRF · файлы .env и секреты
FAQ
QNext.js — безопасный фреймворк?
У Next.js безопасные значения по умолчанию (экранирование вывода и т.д.), и из коробки он довольно надёжен. Но инциденты приходят не из значений по умолчанию в ядре, а из того, как вы обращаетесь с границей сервер/клиент: секреты, которые должны были остаться на сервере, попадают в клиент, забытая авторизация в Server Actions и незакрытые известные CVE зависимостей. На одни значения по умолчанию полагаться нельзя — границей и зависимостями вы управляете сами.
QКак безопасно работать с переменными окружения?
Правило — «секреты остаются на сервере». Добавляйте префикс NEXT_PUBLIC_ только к значениям, безопасным для браузера; никогда — к ключам API или данным подключения (значения NEXT_PUBLIC_ запекаются в клиентский бандл при сборке и видны посетителям). Читайте секреты только внутри серверных компонентов / Server Actions / Route Handlers и проектируйте так, чтобы они не проскользнули в props или ответы.
QНа что обращать внимание в Server Actions?
Server Actions и Route Handlers — это публичные серверные точки входа. Возможность вызвать не означает, что это разрешено. Поверх входа (аутентификации) пишите авторизацию, ограничивающую каждую операцию тем пользователем, которому принадлежит цель. Забудьте про это — и кто-то сможет обновить или удалить чужие данные, просто подменив ID (аутентификация ≠ авторизация). Проверяйте ввод и всегда делайте проверку владельца в действии.