Для тех, кто выкатывает приложения на Next.js (или похожих JS-фреймворках), особенно «собрал с помощью ИИ, эксплуатирую на ощупь». Выжато из реального инцидента (→ заброшенная CVSS 10.0).
Взгляд этого сайта: важна не скорость, а система, которая не пропускает
Когда инди-разработчики не справляются с безопасностью, причина обычно не в нехватке знаний, а в том, что они не могут поддерживать эксплуатацию. Читать новости о CVE быстрее всех не имеет ценности (скорость оставьте вендорам и новостям). Работает система, которая не упустит релевантные вам CVE. Поэтому эта статья сосредоточена на построении такой системы, а не на том, чтобы знать больше.
1. Судите по работающей версии
Измеряйте «на опасной ли я версии» по тому, что реально работает, а не по нижней границе манифеста — потому что число в манифесте и работающая версия часто расходятся.
✗ Считать по нижней границе package.json
"next": "^16.0.0" → «16.0.0 уязвима, значит и мы» — пересчитано как «8 уязвимых».
✓ Считать по работающей версии
npm ls next показывает разрешённую версию → автообновлённые безопасны, отстают лишь зафиксированные. Реально 2.
# see the versions actually resolved
npm ls next react react-dom
# inside a running container
docker exec <container> npm ls nextДиапазоны с кареткой (^16.0.0) автообновляются при пересборке; зафиксированные зависимости отстают. Судите по версиям, показанным здесь.
Как проверить свою конфигурацию
Эти шаги показывают, какая версия вашего приложения реально работает и касается ли её известная CVE. Каждый шаг только осматривает вашу собственную среду.
Проверьте локальную версию
Выполните npx next info в папке проекта. Команда показывает фактические версии next, react и react-dom и насколько вы отстаёте от последнего релиза. npx next -v выводит только версию Next.js.
Выясните, откуда эта версия
npm ls next (или pnpm why next) показывает, какая версия установлена и через какой пакет. Если lock-файл (package-lock.json или pnpm-lock.yaml) не закоммичен, версия может меняться при каждой сборке, поэтому сначала закоммитьте его.
Проверьте версию, работающую в продакшене
Обновление локально не меняет сервер, на котором всё ещё работает старый образ. Для контейнера прочитайте поле version в package.json пакета next внутри работающего контейнера (команда ниже). Это работает и с output: 'standalone'.
Сверьте с известными CVE
npm audit --omit=dev проверяет только зависимости, которые попадают в продакшен. С добавлением --audit-level=high команда завершается с ненулевым кодом при находке уровня High и выше, так что CI может на этом остановиться. Сканирование lock-файла через osv-scanner служит той же цели.
Прочитайте официальное уведомление для вашей конфигурации
Уведомления Next.js иногда различаются для App Router и Pages Router или для самостоятельного и управляемого хостинга. Сравните исправленные версии из уведомления с версиями, найденными в шагах 1–3.
# local: actual versions and distance from latest
npx next info
# the version running inside the production container
docker exec <container> node -p "require('next/package.json').version"
# check only production dependencies; fail on High or above
npm audit --omit=dev --audit-level=highЧто меняется в зависимости от способа запуска
Одна и та же CVE может затрагивать вас или нет в зависимости от того, как вы запускаете Next.js. Два прошлых случая по типам развёртывания:
| Как вы запускаете | Обход авторизации в middleware (CVE-2025-29927) | RCE в RSC (CVE-2025-55182) | Кто обновляет |
|---|---|---|---|
| Управляемый хостинг (Vercel, Netlify и т. п.) | Не затронут (маршрутизация работает в отдельной системе) | Затронут, если вы используете App Router; правила блокировки есть, но обновляться всё равно нужно | Вы (следующую версию определяет ваш lock-файл) |
| Самостоятельный хостинг (next start / standalone, включая Docker) | Затронут | Затронут, если вы используете App Router | Вы (через пересборку образа и перезапуск) |
| Статический экспорт (output: 'export') | Не затронут (сервер не работает) | Нет сервера, принимающего запросы, поэтому в общем случае до вас не доходит | Вы (зависимости времени сборки всё равно нужно обновлять) |
Так что даже на управляемом хостинге поднимать версию Next.js — ваша задача. Считайте защиту хостинга выигрышем времени, пока вы не перейдёте на исправленную версию.
Проверьте и сроки поддержки. По официальной политике поддержки, на октябрь 2026 года:
| Линия | Статус (октябрь 2026) | Исправления безопасности |
|---|---|---|
| 16.x | Active LTS (функции, исправления, патчи безопасности) | Да |
| 15.x | Maintenance LTS (два года с первоначального релиза) | Только критические |
| 14.x и старше | Не поддерживается | Изредка, для серьёзных проблем, без гарантий |
2. Автоматически мониторьте зависимости
Отслеживание CVE вручную не работает, и пропуск становится инцидентом. Отслеживайте их автоматически с помощью инструмента.
Бесплатный мониторинг зависимостей
osv-scanner scan -L pnpm-lock.yamlНа GitHub включите Dependabot (в репозитории: «Settings» → «Advanced Security» → «Dependabot alerts»). Вы будете получать PR только для CVE, совпадающих с вашими зависимостями.
Важна приоритизация. Позиция этого сайта: ранжируйте по «эксплуатируется ли (KEV)», умноженному на «насколько высок CVSS». Высокий CVSS у того, чем вы не пользуетесь, — малое воздействие; средний балл под активной эксплуатацией — высший приоритет. Именно эта приоритизация — суть работы.
3. Обновление: переходите на исправленную версию, а не на обходную меру
Когда появляется уязвимость, обновите фреймворк до исправленной версии, чтобы устранить саму уязвимость.
Поверхностные меры (недостаточно)
- Блокировать на обратном прокси только запросы, похожие на атаку
- Остановить списания/симптом и назвать «разобрались»
- Оставить саму уязвимость RCE на месте
Корневое исправление (правильно)
- Обновить фреймворк до исправленной версии
- После обновления убедиться, что сигнатура исчезла из логов
- Считать остановку ущерба и устранение первопричины двумя разными задачами и делать обе
Частый провал
«Остановили списания/симптом» ≠ «разобрались». Остановка ущерба и устранение уязвимости — разные задачи. Делайте обе.
Реальный пример: уязвимость React Server Components в декабре 2025 года
Вот как на практике выглядела работа с опубликованной CVE — на примере уязвимости React Server Components (RSC), раскрытой в декабре 2025 года. Всё ниже взято из официальных объявлений React и Next.js и открытых данных CISA.
3 декабря 2025 г.
React раскрыла CVE-2025-55182 (CVSS 10.0), которая может привести к выполнению кода на сервере без аутентификации. В Next.js были затронуты приложения на App Router в версиях 15.x, 16.x и некоторых canary (CVE-2025-66478); Pages Router и Edge Runtime затронуты не были. Обходного пути не было: требовалось обновление до исправленной версии (15.0.5, 15.1.9, 15.2.6, 15.3.6, 15.4.8, 15.5.7, 16.0.7 и др.).5 декабря 2025 г.
CISA добавило её в каталог уязвимостей, эксплуатация которых подтверждена (KEV).6 декабря 2025 г.
Next.js добавила, что приложениям, которые были онлайн и не исправлены по состоянию на 4 декабря, 13:00 по тихоокеанскому времени, следует сменить используемые секреты (API-ключи и т. п.).11 декабря 2025 г.
Пока изучали патч, в том же механизме нашли и исправили ещё две проблемы (отказ в обслуживании и раскрытие исходного кода). Затем исправление отказа в обслуживании оказалось неполным, была выпущена CVE-2025-67779, и тех, кто уже обновился, попросили обновиться снова.
Из этого следуют три эксплуатационных вывода:
- Одно обновление — не конец. Дополнительные исправления того же кода могут приходить с разницей в несколько дней
- Правила блокировки хостинга были дополнением; единственным полным исправлением называлось обновление
- Если вы были онлайн до исправления, помимо обновления смените секреты
Взгляд этого сайта: готово — это когда исправлена версия в продакшене, а не когда вы запустили обновление
Когда дополнительные исправления продолжают выходить, как здесь, «я обновился на прошлой неделе» перестаёт быть надёжным. Оценивайте завершение по тому, что версия, работающая в продакшене, не ниже исправленной версии из последнего уведомления, а не по памяти о проделанной работе. Этот сайт тоже отмечает обновление выполненным только после того, как убедится в пересоздании контейнера и проверит версию, работающую внутри него.
Частые ошибки и как их исправить
- Судить по числу в package.json: установленная версия может отличаться. Проверяйте через
npx next infoилиnpm ls next. - Остановиться на обновлении lock-файла: старая версия работает, пока образ продакшена не пересобран и не перезапущен. Проверяйте версию внутри продакшена.
- Успокоиться после одного обновления: могут прийти дополнительные уведомления. Держите включёнными оповещения Dependabot или аналогов и несколько дней следите за уведомлениями.
- Положиться на правила блокировки хостинга: они могут ловить не все формы атаки. Обновляйтесь.
- Оставаться на неподдерживаемой линии: для 14.x и старше исправления не гарантируются. Планируйте переход на 16.x.
- Пропустить важные для продакшена предупреждения среди шума от dev-зависимостей: сначала запустите
npm audit --omit=dev, чтобы увидеть то, что попадает в продакшен. - Игнорировать период до исправления: за это время секреты могли забрать. Смените API-ключи и пароли БД (→ основы .env и API-ключей).
4. Минимум привилегий, чтобы ограничить ущерб
Проектируйте так, чтобы ущерб оставался ограниченным, если приложение всё же взломают.
Запускайте от непривилегированного пользователя
USER контейнера как root. Тогда взлом достаёт лишь то, что разрешено этому пользователю.Привяжите БД/Redis только к внутренней сети
Разделяйте по сервисам
Это решает, остановится ли взлом на «краже окружения внутри контейнера» или дойдёт до «захвата хоста».
Мы делаем это сами
Этот сайт мониторит свои зависимости на предмет CVE ровно так, как написано здесь, — чтобы пропуск вроде того, с которого всё началось (заброшенная публичная CVSS 10.0), больше не зависел от внимательности человека. Мы говорим «ранжируйте по приоритету (KEV + CVSS)», потому что именно так и работаем.
Читать дальше
- Инцидент: Заброшенная публичная RCE и мошеннические счета
- Глоссарий: CVE · CVSS · RCE
- История: Log4Shell — RCE через зависимость
- Фреймворк: Безопасность Next.js (граница, переменные окружения, CVE зависимостей)
- Приоритизация: ранжирование CVE по CVSS, EPSS и KEV
- Мониторинг: настройка osv-scanner
- Общая картина: много ли уязвимостей в Next.js и React? (что на самом деле показывают данные CVE)
Источники
- Next.js, «Security Advisory: CVE-2025-66478» (3 декабря 2025 г.; обновлено 6 декабря): nextjs.org
- Next.js, «Security Update: December 11, 2025» (CVE-2025-55183 / 55184 / 67779): nextjs.org
- NVD, «CVE-2025-55182»: nvd.nist.gov / CISA, «Known Exploited Vulnerabilities Catalog»: cisa.gov
- Vercel, «React2Shell Security Bulletin»: vercel.com
- Vercel, «Postmortem on Next.js Middleware bypass» (CVE-2025-29927): vercel.com
- Next.js, «Support Policy»: nextjs.org / «next CLI»: nextjs.org / «Static Exports»: nextjs.org
- npm Docs, «npm audit»: docs.npmjs.com / OSV-Scanner, «Usage»: google.github.io / GitHub Docs, «Configuring Dependabot alerts»: docs.github.com