TGViewer
Стародубцев x IT-ХОЗЯЕВА Стародубцев x IT-ХОЗЯЕВА @strdub · 3.9K subscribers
Post #1379 2.15K

Forwarded from 8BitJS

​​Что пошло не так в React Server Components и чему из этого стоит научиться

Последние пару дней во всех фронтенд-пабликах пролетела новость: в React нашли критическую уязвимость с оценкой CVSS 10.0. Она позволяет получить удаленное выполнение кода на сервере. В списках пострадавших оказались все кто используют и/или поддерживают React Server Components (RSC).

Но мне захотелось разобраться с инженерной точки зрения, что же именно оказалось сломано внутри React и почему это вообще стало возможно. А главное, понять, чему мы можем научиться из этого кейса как разработчики, даже если не используем RSC.

Небольшое отступление.

В рамках PR с закрытием уязвимости было решено сделать рефакторинг. И справедливо было подмечено

With this combined commit, people now have to go through a >1500 line patch to try to understand the security relevant changes.

Что за уязвимость

CVE-2025-55182 - критическая уязвимость в React Server Components, которая позволяет, отправив специально сформированный запрос, добиться удаленного выполнения кода на сервере.

В коде было обнаружены три основные причины уязвимости:

1. Несимметричность в плане защиты между кодом клиентской и серверной реализацией
2. Небезопасная десериализация данных Flight-протокола на сервере
3. Незащищенное разрешение модулей и экспортов

Немного контекста

React Server Components

Основная идея состоит в том, что сервер может сам рендерить дерево компонентов, может делать запросы в БД и API. Клиент же получает поток (stream) данных о дереве, а не готовый HTML. React на стороне клиента постепенно собирает готовый результат из данных от сервера и клиентских компонентов.

Flight-протокол

Внутренний протокол React для передачи данных в RSC между клиентом и сервером. Простыми словами, сервер кодирует состояние дерева, ссылки на компоненты, промисы в поток байтов. Со стороны клиента поток читает декодер ReactFlightClient и восстанавливает исходные данные. Аналогично со стороны сервера есть декодер ReactFlightReplyServer, который обрабатывает обратные данные от пользователя.

Разберемся в коде

Рассмотрим на практике два ключевых участка, которые стали причиной уязвимости.

Prototype pollution в ReactFlightReplyServer

Внутри серверного декодера есть функция reviveModel в связке с getOutlineModel, которые рекурсивно обходят данные и "оживляет" их в обычные JS структуры.

Упростим:

function reviveModel(...) {
...
if (typeof value === 'object' && value !== null) {
...
for (const key in value) {
// hasOwnProperty проверка для защиты от вызова унаследованных ключей
if (hasOwnProperty.call(value, key)) {
...
// добавили проверку на __proto__
if (newValue !== undefined || key === '__proto__') {
value[key] = newValue;
}
}
}
}


requireModule и доверие к экспорту

В RSC есть функция requireModule(metadata) для бандлеров, которая по metadata.id находит модуль и по metadata.name выбирает нужный экспорт.

export function requireModule<T>(metadata: ClientReference<T>): T {
const moduleExports = parcelRequire(metadata[ID]);
return moduleExports[metadata[NAME]];
}


Сервер слишком доверяет экспортируемому модулю, поэтому могут сработать запросы вида:

{
"id": "foo",
"name": "__proto__"
}


Из-за чего можно было использовать имя экспорта, которого нет в модуле, но существующего в цепочке прототипов.

Для закрытия уязвимости для экспорта добавили проверку

if (hasOwnProperty.call(moduleExports, metadata[NAME])) {
return moduleExports[metadata[NAME]];
}


Итого

Как мы смогли увидеть, в уязвимости нет каких-то хитростей React, а используется довольно распространенная проблема доверия к данных при десериализации.

Что важного мы можем вынести для себя:

Никогда не доверяйте структуре данных от пользователя. Для защиты фильтруем все опасные ключи из прототипирования (__proto__, constructor, prototype) и/или добавляем подход allowlist для ключей. Для конструкции for...in используем hasOwnProperty.

#8BitJS #React #CVE #security #RSC
  • 🔥 15
  • ❤ 5
  • ✍ 3
  • 👍 1
More from @strdub
  1. Oct 9, 2026«Готово. Тесты не запускал». А откуда тогда такая уверенность? 😕 Мне от агентной разработ…
  2. Oct 8, 2026Post #1876
  3. Oct 8, 2026Как я веду разработку своего SaaS в 2к26 Мой подход простой — обвесить метриками всё до че…
  4. Oct 7, 2026Я в этот раз до Avito.Tech.Conf не доехал, но посмотрел, что там показывали, плюс почитал…
  5. Oct 7, 2026Уже успели попробовать эту имбу? Хочу фидбек в комментариях посмотреть, а то я сейчас ещё…
  6. Oct 5, 2026Вчера — в рабочем чате. Сегодня — на билборде 👀 Такое стремительное развитие карьеры возм…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →